package com.zyj.dynds.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.zyj.dynds.component.DynamicDataSource;
import com.zyj.dynds.consts.DataSourceKey;
import com.zyj.dynds.interceptor.DynamicDataSourceInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@Import({DynamicDataSourceInterceptor.class})
@PropertySource("classpath:jdbc.properties")
@MapperScan(basePackages = "com.zyj.dynds.mapper", sqlSessionFactoryRef = "sqlSessionFactory")
public class DataSourceConfig {

    @Autowired
    private DynamicDataSourceInterceptor dynamicDataSourceInterceptor;

    @Primary
    @Bean(name = "master")
    @ConfigurationProperties(prefix = "spring.datasource.druid.master")
    public static DataSource newDataSourceMaster(){
        return new DruidDataSource();
    }

    @Bean(name = "slave")
    @ConfigurationProperties(prefix = "spring.datasource.druid.slave")
    public static DataSource newDataSourceSlave(){
        return new DruidDataSource();
    }

    @Bean(name = "dynamicDataSource")
    public DynamicDataSource newDynamicDataSource(@Qualifier("master")DataSource dataSourceMaster,
                                                  @Qualifier("slave") DataSource dataSourceSlave){
        Map<Object,Object> targetDataSources = new HashMap<>(8);
        targetDataSources.put(DataSourceKey.master, dataSourceMaster);
        targetDataSources.put(DataSourceKey.slave, dataSourceSlave);
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(dataSourceMaster);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }

    @Bean(name = "sqlSessionFactory")
    @ConditionalOnMissingBean
    public SqlSessionFactory newSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource)
            throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        // 自定义拦截器
        factoryBean.setPlugins(new Interceptor[]{dynamicDataSourceInterceptor});
        // 指定Mapper文件路径
        Resource[] mapperLocations = new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*Mapper.xml");
        factoryBean.setMapperLocations(mapperLocations);
        // 设置数据源
        factoryBean.setDataSource(dynamicDataSource);
        return factoryBean.getObject();
    }

    /**
     * 注入 DataSourceTransactionManager 用于事务管理
     */
    @Bean
    public PlatformTransactionManager transactionManager(@Qualifier("master")DataSource dataSourceMaster,
                                                         @Qualifier("slave") DataSource dataSourceSlave) {
        return new DataSourceTransactionManager(newDynamicDataSource(dataSourceMaster, dataSourceSlave));
    }
}
